package com.jixiang.user.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.db.Page;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.jixiang.common.constants.UserConstants;
import com.jixiang.model.common.dtos.ResponseResult;
import com.jixiang.model.common.enums.AppHttpCodeEnum;
import com.jixiang.model.user.dtos.*;
import com.jixiang.model.user.entity.UsUserInfo;
import com.jixiang.user.dao.UsUserDao;
import com.jixiang.model.user.entity.UsUser;
import com.jixiang.user.service.UsUserInfoService;
import com.jixiang.user.service.UsUserService;
import com.jixiang.utils.common.AppJwtUtil;
import com.jixiang.utils.common.MD5Utils;
import com.jixiang.utils.phone.RegexUtils;
import com.jixiang.utils.thread.UserThread;
import lombok.extern.slf4j.Slf4j;
import org.apache.hadoop.hbase.util.JSONBean;
import org.junit.Test;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.concurrent.ListenableFutureCallback;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

import static com.jixiang.common.constants.CodeMqConstants.*;
import static com.jixiang.common.constants.RedisConstants.*;
import static com.jixiang.common.constants.UserConstants.*;
import static com.jixiang.model.common.enums.AppHttpCodeEnum.*;

/**
 * (UsUser)表服务实现类
 *
 * @author makejava
 * @since 2023-10-12 13:57:50
 */
@Slf4j
@Service("usUserService")
public class UsUserServiceImpl extends ServiceImpl<UsUserDao, UsUser> implements UsUserService {
    @Resource
    private UsUserService usUserService;

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Resource
    RedissonClient redissonClient;

    @Autowired
    RabbitTemplate rabbitTemplate;

    @Resource
    private UsUserInfoService usUserInfoService;
    @Override
    public ResponseResult loginAdmin(AdminUserDtos adminUserDtos) {
        UsUser usUser = usUserService.query().eq("user_name", adminUserDtos.getUsername()).one();
        if(usUser ==null ){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST,"用户信息不存在");
        }
        System.out.println(usUser.getUserLevel());
        System.out.println(USER_LEVEL_ADMIN);
        if(!usUser.getUserLevel().equals(USER_LEVEL_ADMIN) ){
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_ADMIND);
        }

        String password = MD5Utils.encode(adminUserDtos.getPassword());
        if(!usUser.getUserPassword().equals(password)){
            return ResponseResult.errorResult(LOGIN_PASSWORD_ERROR);
        }

        String token = AppJwtUtil.getToken(usUser.getId().longValue());
        AdminUserResponseDto adminUserResponseDto =new AdminUserResponseDto();
        adminUserResponseDto.setUserId(usUser.getId().toString());
        adminUserResponseDto.setToken(token);
        return ResponseResult.okResult(adminUserResponseDto);
    }

    @Override
    public ResponseResult getAdminList(int pageNum, int pageSize, String name,String phone) {
        PageHelper.startPage(pageNum, pageSize);
        List<UsUser> list = usUserService.query().orderByDesc("update_time").like(StrUtil.isNotBlank(name), "user_name", name).like(StrUtil.isNotBlank(phone), "user_phone", phone).eq("user_level",USER_LEVEL_ADMIN).list();
        PageInfo page = new PageInfo(list);
        return ResponseResult.okResult(page);
    }

    @Override
    public ResponseResult updateUserState(String id) {
        UsUser usUser = getById(id);
        if (usUser.getUserState()==(USER_STATE_NORMAL)) {
            usUser.setUserState(Integer.valueOf(USER_STATE_DISABLED));
        }else {
            usUser.setUserState(Integer.valueOf(USER_STATE_NORMAL));
        }
        boolean b = updateById(usUser);
        return  ResponseResult.okResult("修改成功");
    }

    @Override
    public ResponseResult getAdminById(String id) {
        UsUser usUser = getById(id);
        usUser.setUserPassword("12345678");
        return  ResponseResult.okResult(usUser);
    }

    @Override
    public ResponseResult updateAdmin(UsUser usUser) {
        String password = MD5Utils.encode(usUser.getUserPassword());
        usUser.setUserPassword(password);
        boolean flag = updateById(usUser);
        return  ResponseResult.okResult("修改成功");
    }

    @Override
    public ResponseResult deleteAdminById(String id) {
        boolean b = removeById(id);
        return ResponseResult.okResult("删除成功");
    }

    @Override
    public ResponseResult addAdmin(UsUser usUser) {
        usUser.setUserLevel(USER_LEVEL_ADMIN);
        usUser.setUserState(USER_STATE_NORMAL);
        boolean save = save(usUser);
        return ResponseResult.okResult("添加成功");
    }

    @Override
    public ResponseResult getUserList(int pageNum, int pageSize, String name, String phone) {
        PageHelper.startPage(pageNum, pageSize);
        List<UsUser> list = usUserService.query().orderByDesc("update_time").like(StrUtil.isNotBlank(name), "user_name", name).like(StrUtil.isNotBlank(phone), "user_phone", phone).list();
        PageInfo page = new PageInfo(list);
        return ResponseResult.okResult(page);
    }

    @Override
    public ResponseResult updateUserLevel(String id) {
        UsUser usUser = getById(id);
        if (usUser.getUserLevel()==(USER_LEVEL_NORMAL)) {
            usUser.setUserLevel(Integer.valueOf(USER_LEVEL_ADMIN));
        }else {
            usUser.setUserLevel(Integer.valueOf(USER_LEVEL_NORMAL));
        }
        boolean b = updateById(usUser);
        return  ResponseResult.okResult("修改成功");
    }

    @Override
    public ResponseResult addUser(UsUser usUser) {
        usUser.setUserLevel(USER_LEVEL_NORMAL);
        usUser.setUserState(USER_STATE_NORMAL);
        boolean save = save(usUser);
        return ResponseResult.okResult("添加成功");
    }

    @Override
    public ResponseResult appSendCode(String phone) {
        if(RegexUtils.isPhoneInvalid(phone)){
            return ResponseResult.errorResult(500,"不符合手机号规范");
        }
        // 1.创建CorrelationData
        CorrelationData cd = new CorrelationData(UUID.randomUUID().toString());
        // 2.给Future添加ConfirmCallback
        cd.getFuture().addCallback(new ListenableFutureCallback<CorrelationData.Confirm>() {
            @Override
            public void onFailure(Throwable ex) {
                // 2.1.Future发生异常时的处理逻辑，基本不会触发
                log.error("send message fail", ex);
            }
            @Override
            public void onSuccess(CorrelationData.Confirm result) {
                // 2.2.Future接收到回执的处理逻辑，参数中的result就是回执内容
                if(result.isAck()){ // result.isAck()，boolean类型，true代表ack回执，false 代表 nack回执
                    log.debug("发送消息成功，收到 ack!");
                }else{ // result.getReason()，String类型，返回nack时的异常描述
                    log.error("发送消息失败，收到 nack, reason : " + result.getReason());
                }
            }
        });
        rabbitTemplate.convertAndSend(MQ_EXCHANGE_CODE,MQ_ROUTINGKEY_CODE,phone,cd);
        return ResponseResult.okResult("已经成功");
    }

    @Override
    public ResponseResult appLoginByUsername(String name, String password) {
        List<UsUser> list = query().eq("user_name", name).list();

        if(list == null || list.isEmpty()){
            ResponseResult.errorResult(LOGIN_NOPER_ERROR,"无此用户");
        }
        UsUser usUser = list.get(0);
        String md5password = MD5Utils.encode(password);
        if(!usUser.getUserPassword().equals(md5password)){
            ResponseResult.errorResult(LOGIN_PASSWORD_ERROR);
        }
        AppUserDtos appUserDtos = getAppUserDtos(usUser.getId());
        return ResponseResult.okResult(appUserDtos);
    }

    @Override
    public ResponseResult appLoginByPhone(String phone, String password) {
        if(RegexUtils.isPhoneInvalid(phone)){
            return ResponseResult.errorResult(500,"不符合手机号规范");
        }
        String redisdata = stringRedisTemplate.opsForValue().get(REDIS_PREX_PHONE + phone);
        if(redisdata == null || redisdata.equals("")){
            return ResponseResult.errorResult(LOGIN_CODE_EXPIER);
        }
        if(!redisdata .equals(password)){
            return ResponseResult.errorResult(LOGIN_PASSWORD_ERROR,"验证码错误");
        }
        UsUser user = new UsUser();
        List<UsUser> list = query().eq("user_phone", phone).list();
        if(list == null || list.isEmpty()){
            user = saveNewUser(phone);
        }else {
//            UsUser usUser1 = saveNewUser(phone);
            user = list.get(0);
        }
        if(user.getUserState()==USER_STATE_DISABLED){
            return ResponseResult.errorResult(USER_DIS);
        }
        AppUserDtos appUserDtos = getAppUserDtos(user.getId());

        return ResponseResult.okResult(appUserDtos);
    }

    @Override
    public ResponseResult wxAppLoginByPhone(String phone) {
        if(RegexUtils.isPhoneInvalid(phone)){
            return ResponseResult.errorResult(500,"不符合手机号规范");
        }
        UsUser user = new UsUser();
        List<UsUser> list = query().eq("user_phone", phone).list();
        if(list == null || list.isEmpty()){
            user = saveNewUser(phone);
        }else {
//            UsUser usUser1 = saveNewUser(phone);
            user = list.get(0);
        }
        if(user.getUserState()==USER_STATE_DISABLED){
            return ResponseResult.errorResult(USER_DIS);
        }

        UsUserInfo userInfo = usUserInfoService.getById(user.getId());
        if(userInfo==null){
            userInfo = saveNewUserInfo(user);
            Date userBirthday = userInfo.getUserBirthday();
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
            String format = simpleDateFormat.format(userBirthday);
            userInfo.setUserBirthdayStr(format);
        }else {
            Date userBirthday = userInfo.getUserBirthday();
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
            String format = simpleDateFormat.format(userBirthday);
            userInfo.setUserBirthdayStr(format);
        }
        AppUserDtos appUserDtos = getAppUserDtos(user.getId(),userInfo);
        return ResponseResult.okResult(appUserDtos);
    }

    @Override
    public Boolean updateWxUserIconImage(WxIconDtos wxIconDtos) {
        UsUser usUser = getById(wxIconDtos.getUserId());
        usUser.setUserIcon(wxIconDtos.getUserNewIconUrl());
        boolean b = updateById(usUser);
        return b;
    }

    @Override
    public ResponseResult wxAppGetwxUserData() {
//        AppWxUserDtos wxUserDtos = new AppWxUserDtos();
//        Long userId = UserThread.getUser().getId();
//        UsUser usUser = getById(userId);
//        UsUserInfo byId = usUserInfoService.getById(userId);
//
//        Date userBirthday = byId.getUserBirthday();
//        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
//        String format = simpleDateFormat.format(userBirthday);
//        byId.setUserBirthdayStr(format);
//        wxUserDtos.setUserDetailInfo(byId);
//        wxUserDtos.setUserInfo(usUser);

        Long userId = UserThread.getUser().getId();
        UsUser usUser = getById(userId);
        AppWxUserDtos appWxUserDtos = BeanUtil.copyProperties(usUser, AppWxUserDtos.class);
        UsUserInfo usUserInfo = usUserInfoService.getById(userId);
        appWxUserDtos.setUserCareer(usUserInfo.getUserCareer());
        appWxUserDtos.setUserSex(usUserInfo.getUserSex());
        Date userBirthday = usUserInfo.getUserBirthday();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String format = simpleDateFormat.format(userBirthday);
        appWxUserDtos.setUserBirthdayStr(format);
        appWxUserDtos.setUserCity(usUserInfo.getUserCity());
        return ResponseResult.okResult(appWxUserDtos);
    }

    @Override
    public ResponseResult wxAppUpdateWxUser(AppWxUserDtos appWxUserDtos) {
        Long userId = UserThread.getUser().getId();
        UsUser usUser = getById(userId);
        usUser.setUserNickname(appWxUserDtos.getUserNickname());
        updateById(usUser);
        UsUserInfo usUserInfo = usUserInfoService.getById(userId);
        usUserInfo.setUserCareer(appWxUserDtos.getUserCareer());
        usUserInfo.setUserSex(appWxUserDtos.getUserSex());
        usUserInfo.setUserCity(appWxUserDtos.getUserCity());
        String userBirthdayStr = appWxUserDtos.getUserBirthdayStr();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date date = new Date();
        try {
            date = simpleDateFormat.parse(userBirthdayStr);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
        usUserInfo.setUserBirthday(date);
        usUserInfoService.updateById(usUserInfo);
        return ResponseResult.okResult("修改个人信息成功");
    }

    private UsUserInfo saveNewUserInfo(UsUser user) {
        UsUserInfo usUserInfo = new UsUserInfo();
        usUserInfo.setId(user.getId());
        usUserInfo.setUserAge(18);
        usUserInfo.setUserBirthday(new Date());
        usUserInfo.setUserSex(1);
        usUserInfo.setUserCreateType(0);
        usUserInfo.setUserCreateUserid(user.getId());
        boolean save = usUserInfoService.save(usUserInfo);
        return usUserInfo;
    }

    private UsUser saveNewUser(String phone){
        UsUser usUser = new UsUser();
        usUser.setUserPhone(phone);
        String substring = phone.substring(6, 6);
        usUser.setUserPassword(MD5Utils.encode(substring));
        usUser.setUserLevel(USER_LEVEL_NORMAL);
        usUser.setUserState(USER_STATE_NORMAL);
        String name = RandomUtil.randomNumbers(8);
        usUser.setUserName(name);
        String nickname = "new_"+RandomUtil.randomNumbers(6);
        usUser.setUserNickname(nickname);
        boolean save = save(usUser);
        return usUser;
    }

    private AppUserDtos getAppUserDtos (Long id) {
        UsUser usUser = getById(id);
        AppUserDtos appUserDtos = new AppUserDtos();
        appUserDtos.setUserInfo(usUser);
        appUserDtos.setUserId(id.toString());
        String token = AppJwtUtil.getToken(id);
        appUserDtos.setToken(token);
        return appUserDtos;
    }
    private AppUserDtos getAppUserDtos (Long id,UsUserInfo usUserInfo) {
        UsUser usUser = getById(id);
        AppUserDtos appUserDtos = new AppUserDtos();
        appUserDtos.setUserInfo(usUser);
        appUserDtos.setUserId(id.toString());
        String token = AppJwtUtil.getToken(id);
        appUserDtos.setToken(token);
        appUserDtos.setUserDetailInfo(usUserInfo);
        return appUserDtos;
    }
}

